package cn.dduan.fool.design.pattern.structure.combine;

import java.util.ArrayList;
import java.util.List;

/**
 * 组合模式
 * <p>
 * 优点：
 * 1、组合模式使得客户端代码可以一致地处理单个对象和组合对象，无须关心自己处理的是单个对象，还是组合对象，这简化了客户端代码
 * 2、更容易在组合体内加入新的对象，客户端不会因为加入了新的对象而更改源代码，满足【开闭原则】
 * <p>
 * 缺点：
 * 1、设计较复杂，客户端需要花更多时间理清类之间的层次关系
 * 2、不容易限制容器中的构件
 * 3、不容易用继承的方法来增加构件的新功能
 * <p>
 * 应用场景：
 * 1、在现实生活中，存在很多“部分-整体”的关系，例如：汽车与轮胎、发动机的关系。医院与科室、医生的关系
 * 2、组合模式是一种非常普遍和常用的模式，接口服务互相组合，提供更丰富的接口，实现复杂的业务逻辑。一般情况会选择使用组合代替继承，组合更灵活、更方便
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
public class CombinePattern {
    public static void main(String[] args) {
        //总文件夹
        Folder zwjj = new Folder("总文件夹");
        //向总文件夹中放入三个文件：1.txt、2.jpg、1文件夹
        TextFile aText = new TextFile("a.txt");
        ImagerFile bImager = new ImagerFile("b.jpg");
        Folder cFolder = new Folder("C文件夹");

        zwjj.add(aText);
        zwjj.add(bImager);
        zwjj.add(cFolder);

        //向C文件夹中添加文件：c_1.txt、c_1.rmvb、c_1.jpg
        TextFile cText = new TextFile("c_1.txt");
        ImagerFile cImage = new ImagerFile("c_1.jpg");
        VideoFile cVideo = new VideoFile("c_1.rmvb");

        cFolder.add(cText);
        cFolder.add(cImage);
        cFolder.add(cVideo);

        //遍历C文件夹
        cFolder.display();
        //将c_1.txt删除
        cFolder.remove(cText);
        System.out.println("-----------------------");
        cFolder.display();

    }
}

/**
 * Component ：抽象构建类，组合中的对象声明接口，在适当的情况下，实现所有类共有接口的默认行为
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
abstract class File {
    String name;

    public File(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract void display();
}

/**
 * Composite：容器对象，定义有枝节点行为，用来存储子部件，在Component接口中实现与子部件有关操作，如增加(add)和删除(remove)等
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class Folder extends File {
    private List<File> files;

    public Folder(String name) {
        super(name);
        files = new ArrayList<File>();
    }

    /**
     * 浏览文件夹中的文件
     */
    @Override
    public void display() {
        for (File file : files) {
            file.display();
        }
    }

    /**
     * @param file
     * @return void
     * @desc 向文件夹中添加文件
     */
    public void add(File file) {
        files.add(file);
    }

    /**
     * @param file
     * @return void
     * @desc 从文件夹中删除文件
     */
    public void remove(File file) {
        files.remove(file);
    }
}

/**
 * Leaf：叶子对象。叶子结点没有子结点
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class TextFile extends File {

    public TextFile(String name) {
        super(name);
    }

    @Override
    public void display() {
        System.out.println("这是文本文件，文件名：" + super.getName());
    }
}

/**
 * Leaf：叶子对象。叶子结点没有子结点
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class ImagerFile extends File {

    public ImagerFile(String name) {
        super(name);
    }

    @Override
    public void display() {
        System.out.println("这是图像文件，文件名：" + super.getName());
    }
}

/**
 * Leaf：叶子对象。叶子结点没有子结点
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class VideoFile extends File {

    public VideoFile(String name) {
        super(name);
    }

    @Override
    public void display() {
        System.out.println("这是影像文件，文件名：" + super.getName());
    }
}